﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using ProjScan.Config;
using ProjScan.ScanRule;
using ProjScan.ScanRuleFixer;
using ProjScan.Tools;
using System.Text;
using UnityEngine;

namespace ProjScan.Modules
{
    //
    // 摘要:
    //     检测模块基类 - Class138
    internal class BaseModules<T1, T2> : Singleton<T1> where T1 : new() where T2 : BaseConfig
    {
        protected StreamWriter rulesSw;

        protected StreamWriter thresSw;

        protected Type ruleAttr;

        protected T2 config;

        //
        // 摘要:
        //     Check规则
        public List<BaseRule> baseRules_Check;

        //
        // 摘要:
        //     Check RecordRule规则
        public List<RecordRule> recordRules_Check;

        //
        // 摘要:
        //     Check GlobalRule
        public List<GlobalRule> globalRules_Check;

        //
        // 摘要:
        //     Fix规则
        public List<BaseRule> baseRules_Fix;

        //
        // 摘要:
        //     Fix RecordRule规则
        public List<RecordRule> recordRules_Fix;

        //
        // 摘要:
        //     Fix GlobalRule规则
        public List<GlobalRule> globalRules_Fix;

        public BaseModules()
        {
            baseRules_Check = new List<BaseRule>();
            recordRules_Check = new List<RecordRule>();
            globalRules_Check = new List<GlobalRule>();
            baseRules_Fix = new List<BaseRule>();
            recordRules_Fix = new List<RecordRule>();
            globalRules_Fix = new List<GlobalRule>();
        }

        public virtual void Fix()
        {
        }

        public virtual void Run(StreamWriter rulesSw)
        {
        }

        public virtual void Run(StreamWriter rulesSw, StreamWriter thresSw)
        {
        }

        //
        // 摘要:
        //     提取规则名称ID
        //
        // 参数:
        //   FullName:
        public static string ExtractRuleName(string FullName)
        {
            return FullName.Substring("ProjScan.ScanRule.".Length);
        }

        //
        // 摘要:
        //     提取规则修复名称ID
        //
        // 参数:
        //   FullName:
        public static string ExtractFixerRuleName(string FullName)
        {
            return FullName.Substring("ProjScan.ScanRuleFixer.Rule.".Length);
        }

        public virtual void Init()
        {
        }

        //
        // 摘要:
        //     删除所有的输出文件
        protected virtual void DeleteOutputFiles()
        {
            for (int i = 0; i < recordRules_Check.Count; i++)
            {
                RecordRule recordRule = recordRules_Check[i];
                recordRule.DeleteOutputFile();
            }
        }

        protected virtual void LoadFixers()
        {
            try
            {
                Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
                foreach (Assembly assembly in assemblies)
                {
                    Type[] types = assembly.GetTypes();
                    foreach (Type type in types)
                    {
                        if (!type.GetInterfaces().Any((Type t) => t.IsGenericType && t.GetGenericTypeDefinition() == typeof(IRuleFixer<>)))
                        {
                            continue;
                        }

                        foreach (RecordRule item in recordRules_Fix)
                        {
                            if (ExtractRuleName(item.GetType().FullName) == ExtractFixerRuleName(type.GetInterfaces()[0].GetGenericArguments()[0].ToString()))
                            {
                                item.fixerType = type;
                            }
                        }

                        foreach (GlobalRule item2 in globalRules_Fix)
                        {
                            if (ExtractRuleName(item2.ToString()) == ExtractFixerRuleName(type.GetInterfaces()[0].GetGenericArguments()[0].ToString()))
                            {
                                item2.fixerType = type;
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                ScanLog.Instance.LogInfo(ScanLog.LogLevel.EXCEPTION, Module.Unknown, "Load Fixers", ((ex.GetType() == null) ? null : ex.GetType().ToString()) + "\n" + ex.Message + "\n" + ex.StackTrace);
            }
        }

        //
        // 摘要:
        //     加载规则 并初始化想要的规则数据
        //
        // 参数:
        //   loadMode:
        protected virtual void LoadRules(LoadMode loadMode)
        {
            Type[] types = Assembly.GetExecutingAssembly().GetTypes();
            foreach (Type type in types)
            {
                if (type.GetCustomAttributes(ruleAttr, inherit: true).Length == 0)
                {
                    continue;
                }

                string text = ExtractRuleName(type.FullName);
                RuleConfig ruleConfig = config.Get(text);
                bool flag = false;
                if (!((loadMode != 0) ? ruleConfig.fixEnabled : ruleConfig.checkEnabled))
                {
                    continue;
                }

                BaseRule baseRule = Activator.CreateInstance(type) as BaseRule;
                if (!baseRule.CheckSupportability(out string msg))
                {
                    Debug.LogError(" 规则 " + type.Name + " 运行失败，不被当前环境支持。" + msg);
                }
                else
                {
                    if (config.hasSeparateTargetDirSettings)
                    {
                        RecordRule recordRule = baseRule as RecordRule;
                        recordRule.hasSeparateTargetDirSettings = true;
                        recordRule.SetDirConfigs(ruleConfig.isSeparateDirSettingsEnabled, ruleConfig.targetConfig, ruleConfig.ignoreConfig);
                    }

                    if (loadMode == LoadMode.Check)
                    {
                        baseRules_Check.Add(baseRule);
                    }
                    else
                    {
                        baseRules_Fix.Add(baseRule);
                    }
                }

                if (baseRule.GetType().IsSubclassOf(typeof(RecordRule)))
                {
                    RecordRule recordRule2 = baseRule as RecordRule;
                    if (loadMode == LoadMode.Check && config.hasWhiteList)
                    {
                        recordRule2.SetWhiteList(WhiteAssetManager.Instance.GetWhiteListForRuleId(text));
                    }

                    if (loadMode != 0 && config.hasfailedData && FailedResultManager.Instance.dicFails.ContainsKey(text))
                    {
                        recordRule2.failAssetInfos = FailedResultManager.Instance.dicFails[text];
                    }

                    if (loadMode == LoadMode.Check)
                    {
                        recordRules_Check.Add(recordRule2);
                    }
                    else
                    {
                        recordRules_Fix.Add(recordRule2);
                    }
                }

                if (baseRule.GetType().IsSubclassOf(typeof(GlobalRule)) && config.hasfailedData)
                {
                    GlobalRule globalRule = baseRule as GlobalRule;
                    if (FailedResultManager.Instance.dicFails.ContainsKey(text))
                    {
                        globalRule.failAssetInfos = FailedResultManager.Instance.dicFails[text];
                    }

                    if (loadMode == LoadMode.Check)
                    {
                        globalRules_Check.Add(globalRule);
                    }
                    else
                    {
                        globalRules_Fix.Add(globalRule);
                    }
                }
            }

            StringBuilder stringBuilder = new StringBuilder();
            foreach (BaseRule item in baseRules_Check)
            {
                stringBuilder.Append(item.GetType().Name).Append(", ");
            }

            Debug.Log("EnabledRules:" + stringBuilder.ToString());
        }

        protected virtual void LoadRules(LoadMode loadMode, string ruleID)
        {
            Type[] types = Assembly.GetExecutingAssembly().GetTypes();
            RecordRule recordRule = default(RecordRule);
            foreach (Type type in types)
            {
                if (type.GetCustomAttributes(ruleAttr, inherit: true).Length == 0)
                {
                    continue;
                }

                string text = ExtractRuleName(type.FullName);
                if (!(text == ruleID))
                {
                    continue;
                }

                RuleConfig ruleConfig = config.Get(text);
                BaseRule baseRule = Activator.CreateInstance(type) as BaseRule;
                if (!baseRule.CheckSupportability(out string msg))
                {
                    ScanLog.Instance.LogInfo(ScanLog.LogLevel.INFO, Module.Unknown, "Load Rules - CheckSupportability[-false-]", type.Name + "@" + Singleton<ScanInfo>.Instance.graphicsDeviceType);
                    Debug.LogError("[ProScanLog] 规则 " + type.Name + " 运行失败，不被当前环境支持。" + msg);
                    continue;
                }

                int num;
                if (config.hasSeparateTargetDirSettings)
                {
                    recordRule = (baseRule as RecordRule);
                    num = ((recordRule != null) ? 1 : 0);
                }
                else
                {
                    num = 0;
                }

                if (num != 0)
                {
                    recordRule.hasSeparateTargetDirSettings = true;
                    recordRule.SetDirConfigs(ruleConfig.isSeparateDirSettingsEnabled, ruleConfig.targetConfig, ruleConfig.ignoreConfig);
                }

                if (loadMode == LoadMode.Check)
                {
                    baseRules_Check.Add(baseRule);
                }
                else
                {
                    baseRules_Fix.Add(baseRule);
                }

                RecordRule recordRule2 = baseRule as RecordRule;
                if (recordRule2 != null)
                {
                    if (loadMode == LoadMode.Check && config.hasWhiteList)
                    {
                        recordRule2.SetWhiteList(WhiteAssetManager.Instance.GetWhiteListForRuleId(ruleID));
                    }

                    if (loadMode != 0 && config.hasfailedData && FailedResultManager.Instance.dicFails.ContainsKey(ruleID))
                    {
                        recordRule2.failAssetInfos = FailedResultManager.Instance.dicFails[ruleID];
                    }

                    if (loadMode == LoadMode.Check)
                    {
                        recordRules_Check.Add(recordRule2);
                    }
                    else
                    {
                        recordRules_Fix.Add(recordRule2);
                    }
                }

                GlobalRule globalRule = baseRule as GlobalRule;
                if (globalRule != null && config.hasfailedData)
                {
                    if (FailedResultManager.Instance.dicFails.ContainsKey(ruleID))
                    {
                        globalRule.failAssetInfos = FailedResultManager.Instance.dicFails[ruleID];
                    }

                    if (loadMode == LoadMode.Check)
                    {
                        globalRules_Check.Add(globalRule);
                    }
                    else
                    {
                        globalRules_Fix.Add(globalRule);
                    }
                }
            }

            StringBuilder stringBuilder = new StringBuilder();
            foreach (BaseRule item in baseRules_Check)
            {
                stringBuilder.Append(item.GetType().Name).Append(", ");
            }

            ScanLog.Instance.LogInfo(Module.Unknown, ScanLog.Stage.s1, "EnabledRules", stringBuilder.ToString());
        }

        public virtual void InitRules(int startId)
        {
            for (int i = 0; i < baseRules_Check.Count; i++)
            {
                baseRules_Check[i].Init();
                baseRules_Check[i].SetDataID(startId + i);
            }
        }

        public virtual void Close()
        {
        }

        public virtual void FixSingle(string ruleId)
        {
        }

        public virtual void UpdateFailedData(BaseRule baseRule_0)
        {
            string fullName = baseRule_0.GetType().FullName;
            FailedResultManager.Instance.UpdateFailedData(fullName, baseRule_0.failAssetInfos);
        }
    }
}